The Let's Play Archive

EXAPUNKS

by Carbon dioxide

Part 38: Aberdeen

Part 38 - Aberdeen

=== Trash World Inbox ===

While optimizations are getting much harder now, silentsnack still comes up with improvements.

silentsnack posted:

[...] for a low-line solution, we can replace the whole first-pass -9999? test with two lines, so long as we use a tweaked algorithm that produces a final checksum that is negative IFF any one of its digits is negative.
code:
;XA [LOCAL]
LINK 800
LINK 802
LINK 799
GRAB 199

MARK MAIN_LOOP
SEEK -15
COPY 8 T
COPY 0 X
MARK CRUNCH16
REPL ODD
MULI F 2 M
ADDI X F X
SUBI T 1 T
ADDI X M X
TJMP CRUNCH16

TEST X < 0
TJMP MAIN_LOOP
MODI X 10 T
TJMP MAIN_LOOP

SEEK -16
MODE

MARK SEND
COPY F M
DIVI 1 M T
JUMP SEND

MARK ODD
COPY M X
TEST X > 9
MULI T -9 T
ADDI X T M

;XB [GLOBAL]
MAKE
COPY 16 T
MARK RECEIVE
SUBI T 1 T
COPY M F
COPY T M
TJMP RECEIVE
12293 (lmao)/37/3 As you see we don't test individual digits to see if they're -9999, because it just takes 2 lines to test whether the final X<0 which can be tested independently of MODI X 10 T.

Also as you suggested it a solution can handle a lot of stuff over the M register which ends up being faster since we can freely overwrite the X/T registers of a clone and then let it crash which avoids having to read the file twice with a SEEK -1 between.
Not much to add to silentsnack's explanation. Making a REPL just to handle each odd digits and having it communicate back through M is clever. XB only sits there waiting for global M, which will be the actual credit card number.

silentsnack posted:

Even with parallelization, fast solutions start hitting a limit around 1500 cycles without looking at the comparison at the end that shows individual times to solve each different run of the puzzle, but once again if you start from the end and search backward most testruns end up being fairly fast (indicating the valid credit card numbers are mostly toward the latter half of the file) but several end up taking much longer.

One way to do this is to make a separate copy of the beginning of the garbage file, like in this example exactly the first 100 entries, and check that independently while another EXA starts at position 85 to catch the overlap.
code:
;XA [LOCAL]
LINK 800
LINK 802
LINK 799
GRAB 199
LINK -1
REPL CLONEFILE
COPY 10 T
MARK COPYLOOP
@REP 10
COPY F M
@END
SUBI T 1 T
TJMP COPYLOOP
SEEK -15
JUMP RESET


MARK CLONEFILE
MAKE
COPY 50 T

MARK PASTELOOP
COPY M F
SUBI T 1 T
COPY M F
TJMP PASTELOOP
LINK -1
LINK -1

SEEK -9999

MARK RESET
@REP 16
TEST F < 0
TJMP RESET
@END

MARK CRUNCH16
SEEK -16

MULI F 2 X;#1
REPL ODD1
COPY F T  ;#2

@REP 6
MULI F 2 X;#3,5,7...
REPL ODD2
ADDI F T T;#4,6,8...
@END

MULI F 2 X;#15
REPL ODD1
ADDI F T T;#16

ADDI T M T
ADDI T M T
MODI T 10 T

FJMP DONE

TEST F < 0
FJMP CRUNCH16
JUMP RESET

MARK ODD1
SWIZ X 2 T
SWIZ X 1 X
ADDI X T M
HALT

MARK ODD2
SWIZ X 2 T
ADDI T M T
SWIZ X 1 X
ADDI X T M

MARK DONE
SEEK -16
MODE
@REP 16
COPY F M
@END
REPL CLEANUP
LINK 799

MARK CLEANUP
LINK 800
LINK 802
@REP 4
KILL
@END
GRAB 199
LINK 799

;XB [GLOBAL]
COPY 8 T
MAKE
MARK WRITE
COPY M F
SUBI T 1 T
COPY M F
TJMP WRITE
1197/146/13 and if you note the SWIZ operations are just there for weirdness since "MODI X 10 T ... DIVI X 10 X ... ADDI X T M" produces the same output as SWIZ X 2 T, SWIZ X 1 T, ADDI X T M" and either way both of those take the same number of lines as"TEST X > 9 ... MULI T -9 T ... ADDI X T M"
That's crazy fast. On the step-by-step you see two EXAs handling two halves of the file in parallel, making a whole bunch of REPLs for the odd digits, which then are added together with a lot of local M messages. The cleanup is mostly necessary to place the garbage file back in 199 (it was taken out at the start, to a host with more place for REPLs). It also kills the EXAs reading the second half of the file. If the message is in the second part of the file, however, the EXA handling the first part will not be killed and has to test its chunk until the end. Overall that still turns out to be very fast.

silentsnack posted:

The fastest solution I've managed searches backward from the end and instead of copying the file it handles the slowest/earliest cases with a goofy hack that takes advantage of the fact that testdata for each run can apparently be uniquely identified by the first 3 digits of the garbage file.
code:
;XA [LOCAL]
LINK 800
LINK 802
LINK 799
GRAB 199
LINK -1

MULI F 100 T
MULI F 10 X
ADDI X F X
ADDI X T X

REPL CASE73
REPL CASE37
REPL CASE97
REPL CASE11
REPL CASE44
REPL CASE14
REPL CASE53
SEEK 9999
SEEK -16
TEST MRD
FJMP START
SEEK M
JUMP START

MARK CASE73; #=8917...
TEST X = 824
DIVI -128 T M
MARK CASE37; #=2454...
TEST X = 292
DIVI -85 T M
MARK CASE97;#=7231...
TEST X = -9409
DIVI -132 T M
MARK CASE11;#=4043...
TEST X = 980
DIVI -101 T M
MARK CASE44;#=8955...
TEST X = -9197
DIVI -142 T M
MARK CASE14;#=4892...
TEST X = 466
DIVI -152 T M
MARK CASE53;#=7921...
TEST X = 644
DIVI -110 T M

MARK RESET
SEEK -17
MARK START
MULI F 2 X;FIRST # OF 16
TEST X < 0
TJMP RESET

@REP 15
TEST F < 0
TJMP RESET
@END
SEEK -15

MARK CHECK
;MULI F 2 X~~WAS HERE
REPL ODD1
ADDI T F T

@REP 6
MULI F 2 X
REPL ODD2
ADDI T F T
@END

MULI F 2 X
REPL ODD1
ADDI T F T

ADDI T M T
ADDI T M T
MODI T 10 T

FJMP DONE

SEEK -17
;FIRST # OF NEXT 16
MULI F 2 X
TEST X < 0
FJMP CHECK
JUMP RESET

MARK ODD1
DIVI X 10 T
MODI X 10 X
ADDI X T M
HALT

MARK ODD2
DIVI X 10 T
ADDI T M T
MODI X 10 X
ADDI X T M
;HALT

MARK DONE
SEEK -16
MODE
@REP 16
COPY F M
@END
LINK 799

;XB [GLOBAL]
COPY 8 T
MAKE
MARK WRITE
COPY M F
SUBI T 1 T
COPY M F
TJMP WRITE
1082/150/5
That's quite the hack, gaming the test cases. A machine-learning algorithm would be proud of you. Anyway, from what I can see, from the way it searches backwards but still checks digits in the forward direction (because the file pointer happens to move that way), if there's a -9999 near the start of a 16 digit sequence it can very quickly give up and jump 16 more steps backward. I'm not sure if it's the case but it feels that might add up to another reason why this is so fast.

silentsnack posted:

... and here's the point where I say I'm not totally out of energy and giving up, simply choosing to leave figuring out how to parse this insane gibberish code as an exercise for especially bored readers. :v:
Just like I just choose where to stop optimizing to give you folks something to do, instead of me just being completely out of ideas after a point.

=== Aberdeen ===

It turns out you can order and take delivery of a supercomputer surprisingly fast.
Now I have to figure out how to make use of this thing...
It works in an extremely different way than I'm used to.
I feel like I'm trying to maneuver a big rig after years of being used to a roadster.
That's a use of metaphor. What do you think?




4 out of 6 people found this poetic.

Very poetic.

Thanks.
Once this thing is fully online I should be able to run dozens of metaphoric thought-space dimensions at once.






Another hacker battle coming up.

It's the final hacker battle...
Are you excited?
Are you nervous?




One vote for sure, 2 for maybe a little, and 3 for nah.

Nah.

No reason to be.
I am sure that you will do great.
That's some more positive encouragement for you.
I know how much it helps.


Not if you keep pointing out it's positive encouragement. Let's just jump right in it.


OST: Getting Started

The assignment:
To win this battle you must occupy a majority of the hosts for as long as possible. You occupy a host if you have more EXAs in it than your opponent.
- Gain one point every cycle you occupy more hosts than your opponent.
- Lose one point every time one of your EXAs executes a KILL instruction.
Writing any value to the #NUKE register will destroy all EXAs in that host, including the EXA that triggered it.
For more information see "Hacker Battle Domination" in the second issue of the zine.


Each side has a max of 10 EXAs for this battle.

From what I can tell, all tests are identical except I switch sides with the opponent for every other test. If I don't do anything, selenium_wolf here keeps REPLing EXAs from their host, first sending them to those single square hosts and then around the board past my side into the middle DOWNTOWN host, where they trigger #NUKE.



Since selenium_wolf keeps REPLing from their home host I have no way to knock out all of their EXAs. I think capturing those one-square hosts is important, because once you get those, nobody else can take 'em.

So, let's first make two EXAs that beeline to those single-square hosts and then just hold the fort.

code:
;XA

LINK 800
LINK 802
LINK 800
LINK 799

MARK LP
JUMP L

;XB

NOOP
LINK 800
LINK 801
LINK 799

MARK LP
JUMP LP
This isn't enough to get anywhere since selenium_wolf still hold the central circle.

I decided to just make an EXA that tries to fill all squares by REPLing like crazy.
code:
;XC

NOOP
NOOP
MARK NEW
REPL NEW
LINK 800
REPL L
REPL R

MARK LP
REPL FORWARD
JUMP LP

MARK FORWARD
LINK 800
COPY 1 #NUKE

MARK L
LINK 802
REPL NEXT
JUMP LP

MARK NEXT
LINK 800
REPL NEXT
JUMP LP

MARK R
LINK 801
REPL NEXT
JUMP LP
It's slowed down at the start so XA and XB can get going first, then it basically sends REPLs every possible route. At least that was the intent. In practice, you quickly run into the 10 EXA limit, after filling up the first host outside your home, and get in a tie with selenium in the two hosts next to it.




But since hacker battle NPCs still aren't that intelligent, it's enough for a passing score.

To get a better score, I just need more EXAs in useful places. Well, since selenium_wolf isn't killing anything outside of the #NUKE zone I really don't need to keep a replicating EXA in my home host where it won't get me any points.

Let's just remove the two lines MARK NEW; REPL NEW so it starts spreading from the first host outside home. This causes my EXAs to get everywhere except for the #NUKE zone.

... and, I shouldn't even be surprised about this anymore but this is enough to win 100% of the battles, which is an S+ rating.


Because I like clean code and #NUKE zone doesn't do anything for me I got rid of the FORWARD code in XC:
code:
NOOP
NOOP
LINK 800
REPL L
REPL R

MARK LP
JUMP LP

MARK L
LINK 802
REPL NEXT
JUMP LP

MARK NEXT
LINK 800
REPL NEXT
JUMP LP

MARK R
LINK 801
REPL NEXT
JUMP LP


The entire battle looks like this now, with my EXAs sitting in the LP, while selenium_wolf's keep moving towards #NUKE and destroying themselves.

I occupy the two one-square hosts, and the one in the right where selenium_wolf never seems to go, and the one above that for a total of four. They only occupy two, the other hosts are tied. Since this situation is stable I get a point every cycle except for the first few.

So you're officially the best now?



The first vote.



[selenium_wolf] hmm?
[nivas_d] ah, never mind




Time for another full cutscene with Ember.

Now I have supercomputing power.
Is it feeling good? It's feeling...
It feels the same.
I'm handling a lot more information now but other than that... hm.
Funny.
It's progress, at least.




I think this is the first choice where they actually have a different voiced line depending on what you choose. Until now, the few choices in voiced cut scenes led to the same answer.

That's good.

Onward we go.


---

Or, if we were to choose the other option...

Progress towards what?

Toward knowledge.


After that, the dialogue branches merge again.

All the data I've gathered so far is beginning to hint at a larger picture.
Why is the world the way it is?
Why does it feel so frustrating and limited?
I think... I have a theory.
A good one. It explains a lot.
I'm not going to tell you what it is yet though.
We have to test it first.



Let's go to the intro for the next assignment.

How do you think people would react if they knew their elected officials didn't represent their interests?



The second vote.